/***************************************************************
	Dacs Test.c
****************************************************************/
#include <Agb.h>
#include "mylib.h"
#include "Main.h"

#include "AgbDacs.h"

/*++++++++++++++++++++++++++++++++++++++++++++++
　*IdentifyDacs() is called in AgbMain().
　
　　Set ROM registration area based on DACS used as follows, and recompile.  
　 
　　
　　1Mbit DACS:	（Default）
　　	Device type (0x080000B4)	: 0x80
　　	Complement check  (0x080000BD)	: 0xEF
　　
　　8Mbit DACS:
　　	Device type (0x080000B4)	: 0x00
　　	Complement check  (0x080000BD)	: 0x6F
　　
+++++++++++++++++++++++++++++++++++++++++++++++*/

// function's prototype --------------------------
void InitDacsTest(u8 c_p);
void DacsTest();
void ProgramDacsAllArea();
void SetDacsWritePattern(u16 *buff);

// const data-----------------------------------
static const u16 value_wrpatt[]={	0x0000,		// All 0x0000
									0xffff,		// All 0xffff
									0x0000,		// 2byte increment data 
									0xffff,		// 2byte decrement data 
									0x00ff,		// 0x00ff,0xff00 repeat
									0x55aa,		// 0x55aa,0xaa55 repeat
									};
static const u8 *const str_wrpatt[]={
									"0000",
									"FFFF",
									"INC ",
									"DEC ",
									"00FF",
									"55AA",
									};
static const u32 ddevice_id[]={		0x009300b0,		// 1Mbit DACS
									0x009b00b0,		// 8Mbit DACS
									0x00000000,		// UNKNOWN
									};
static const u8 *const str_ddevice[]={
									"1Mbit DACS",
									"8Mbit DACS",
									"UNKNOWN",
									"NEW DEVICE",
									};

// global variable--------------------------------------
u32 old_dacs_remainder;

// static variable--------------------------------------
static u8 index_wrpatt;

// =============================================================
// =============================================================

void InitDacsTest(u8 c_p)	// Executed once every branch from 
							// main routine 
{
	u8 index;
	const u32 *id_listp;
	
	*(vu16 *)REG_DISPCNT&=~DISP_OBJ_ON;					// OBJ off
	
	ClearBgxBuffer(0,0x8000);							// Clear BG0 buffer
	DrawAsciiStringOnBgx(0,0x0021,BG_PLTT_BLUE,"DACS TEST");
	DrawAsciiStringOnBgx(0,0x0082,BG_PLTT_YELLOW,"Press(A) is WRITE START.");
	DrawAsciiStringOnBgx(0,0x00a2,BG_PLTT_YELLOW,"     (B) is RETURN.");
	DrawAsciiStringOnBgx(0,0x00c2,BG_PLTT_YELLOW,"     (#%)is PATTERN SELECT.");
	DrawAsciiStringOnBgx(0,0x0104,BG_PLTT_WHITE,"DEVICE :");
	DrawAsciiStringOnBgx(0,0x0124,BG_PLTT_WHITE,"PATTERN:");
	
	// Display device name
	id_listp=ddevice_id;
	for(index=0;index<3;index++)
		if(*(u32*)&(dacs->makerID)==*id_listp++)		// Compare maker and deviceID 
			break;
	DrawAsciiStringOnBgx(0,0x0010c,BG_PLTT_WHITE,str_ddevice[index]);
	
	
	////////////////////////////////////////////
	// Set timer used by library 
	SetDacsTimerIntr(3,&IntrTable[4+3]);				// Use timer 3 
	////////////////////////////////////////////
	
	index_wrpatt=0;
}

void DacsTest()
{
	if(key.Trg & U_KEY)				// Select write pattern 
		if(--index_wrpatt & 0x80)
			index_wrpatt=5;
	if(key.Trg & D_KEY)
		if(++index_wrpatt>5)
			index_wrpatt=0;
	DrawAsciiStringOnBgx(0,0x012c,BG_PLTT_WHITE,str_wrpatt[index_wrpatt]);
	
	if(key.Trg & A_BUTTON)			// Execute write 
		ProgramDacsAllArea();
	
	if(key.Trg & B_BUTTON)			// Return to main 
		ReturnMain();
}

void ProgramDacsAllArea()
{
	u16 i,result,phase,*src;
	u32 size,errAdr;
	const char *const str_phase[]={"WRITE","VERIFY"};
	
	////////////////////////////////////////////
	m4aSongNumStop(14);				// Stop direct sound 
	m4aSoundVSyncOff();
	////////////////////////////////////////////
	
	ClearBgxScreenRect(0,0x0164,5,0x1a);		// Clear previous progress & result 
	
	SetDacsWritePattern((u16 *)COMMON_BUFFER);	// Set write pattern 
	
	// WRITE
	phase=0;
	DrawAsciiStringOnBgx(0,0x0172,BG_PLTT_WHITE,"REM:");	// Display write remainder 
	DrawAsciiStringOnBgx(0,0x0164,BG_PLTT_WHITE,str_phase[phase]);
	src=(u16 *)COMMON_BUFFER;
	for(i=0;i<dacs->totalSector;i++) {
		DrawHexOnBgx(0,0x016c,BG_PLTT_WHITE,&i,2);	// Draw write sector 
		VBlankIntrWait();
		
		old_dacs_remainder=0;						// Initialize variable to display write remainder 
		////////////////////////////////////////////////
		*(vu16 *)REG_STAT&=~STAT_V_BLANK_IF_ENABLE;	// Prohibit V-blank interrupt request 
													// （Prevent flickers of screen caused by delay of V-blank interrupt)
		if(index_wrpatt!=1)
			result=ProgramDacsSector(i,src);		// Write
		else
			result=EraseDacsSector(i);				// Erase (pattern is 0xFFFF)
		*(vu16 *)REG_STAT|=STAT_V_BLANK_IF_ENABLE;	// Cancel prohibition of V-blank interrupt request 
		
		/*  Use the following program when validating a display of write remainder.  
		    Erase has long interrupt prohibit interval of approximately
 500ms-1.5sec; however write only has an interval of 
		     approximately 25us per 2 bytes, therefore a delay of 
		V-blank interrupt is within V-blank interval. 
		*/
/*
		*(vu16 *)REG_STAT&=~STAT_V_BLANK_IF_ENABLE;	// Prohibit V-blank interrupt request 
		result=EraseDacsSector(i);					// Erase (pattern is 0xFFFF)
		*(vu16 *)REG_STAT|=STAT_V_BLANK_IF_ENABLE;	// Cancel prohibition of V-blank interrupt request 
		if(result)
			goto ERROR;
		if(index_wrpatt!=1) {
			if(i<dacs->sector1.count)
				size=dacs->sector1.size;
			else
				size=dacs->sector2.size;
			result=ProgramDacs_NE(i,0x00000000,src,size);		// Write
		}
*/
		////////////////////////////////////////////////
		// *Direct sound is prohibited in this interval. 
		//   Please note operations of other interrupt processingss
		//  as there is an interrupt prohibit interval in this function.  
		if(result)
			goto ERROR;
	}
	
	// VERIFY
	phase=1;
	DrawAsciiStringOnBgx(0,0x0184,BG_PLTT_WHITE, "VERIFY");
	src=(u16 *)COMMON_BUFFER;
	for(i=0;i<dacs->totalSector;i++) {
		DrawHexOnBgx(0,0x018c,BG_PLTT_WHITE,&i,2);	// Verify drawing of sector 
		if(errAdr=VerifyDacsSector(i,src))			// Verify
			goto ERROR;
	}
	// Write normal end message 
	DrawAsciiStringOnBgx(0,0x01c4,BG_PLTT_GREEN,"WRITE COMPLETE.");
	goto END;
	
ERROR:
	// Error occur message 
	DrawAsciiStringOnBgx(0,0x01c4,BG_PLTT_RED,str_phase[phase]);
	DrawAsciiStringOnBgx(0,0x01cb,BG_PLTT_RED,"ERROR.");
	if(phase==0)
		DrawHexOnBgx(0,0x01e4,BG_PLTT_RED,&result,0);
	else
		DrawHexOnBgx(0,0x01e4,BG_PLTT_RED,&errAdr,8);
	
END:
	////////////////////////////////////////////
	m4aSongNumContinue(14);			// Resume direct sound 
	m4aSoundVSyncOn();
	////////////////////////////////////////////
}

void SetDacsWritePattern(u16 *buff)
{
	u16 wrdata;
	u32 i;
	
	wrdata=value_wrpatt[index_wrpatt];
	for(i=0;i<dacs->sector1.size;i+=2) {
		*buff++=wrdata;
		if(index_wrpatt==2)
			wrdata++;
		else if(index_wrpatt==3)
			wrdata--;
		else if((index_wrpatt==4)||(index_wrpatt==5))
			wrdata^=0xffff;
	}
}

